home *** CD-ROM | disk | FTP | other *** search
- .MODEL large,PASCAL
- .DATA
- .CODE
- detect PROC FAR RETURNS EnvVal:WORD
-
- PUBLIC detect
-
- push di
- push ds
- push es
-
- ; Is It an 8088/8086?
- pushf
- pushf ; Push the flags so
- pop bx ; we can pop them into bx
- and bx,00fffh ; Mask off bits 12-15
- push bx ; and put it back on the stack
- popf ; Pop value back into the flags
- pushf ; Push it back. 8088/8086 will
- ; have bits 12-15 set
- pop bx ; Get value into bx
- popf ; Restore the flags
- and bx,0f000h ; Mask all but bits 12-15
- cmp bx,0f000h ; See if the bits are still set
- jz Not286 ; Jump if not
- jmp AtLeast286
- Not286:
- ; Is It an 8086?
- ; Returns ax==0 for 8088, ax==1 for 8086
- ; Code takes advantage of the 8088's 4-byte prefetch queues and 8086's
- ; 6-byte prefetch queues. By self-modifying the code at a location exactly 5
- ; bytes away from IP, and determining if the modification took effect,
- ; you can differentiate between 8088s and 8086s.
- mov ax,cs ; es == code segment
- mov ds,ax
- mov es,ax
- std ; Cause stosb to count backwards
- mov dx,1 ; dx is flag and we'll start at 1
- mov di,offset EndLabel ; di==offset of code tail to modify
- mov al,090h ; al==nop instruction opcode
- mov cx,3 ; Set for 3 repetitions
- rep stosb ; Store the bytes
- cld ; Clear the direction flag
- nop ; Three nops in a row
- nop ; provide dummy instructions
- nop
- dec dx ; Decrement flag (only with 8088)
- nop ; dummy instruction--6 bytes
- EndLabel:
- nop
- mov ax,dx ; Store the flag in ax
- jmp detectret
- AtLeast286:
- ; Is It an 80286?
- ; Determines whether processor is a 286 or higher. Going into subroutine ax = 2
- ; If the processor is a 386 or higher, ax will be 3 before returning. The
- ; method is to set ax to 7000h which represent the 386/486 NT and IOPL bits
- ; This value is pushed onto the stack and popped into the flags (with popf).
- ; The flags are then pushed back onto the stack (with pushf). Only a 386 or 486
- ; will keep the 7000h bits set. If it's a 286, those bits aren't defined and
- ; when the flags are pushed onto stack these bits will be 0. Now, when ax is
- ; popped these bits can be checked. If they're set, we have a 386 or 486.
- pushf ; Preserve the flags
- mov ax,7000h ; Set the NT and IOPL flag
- ; bits only available for
- ; 386 processors and above
- push ax ; push ax so we can pop 7000h
- ; into the flag register
- popf ; pop 7000h off of the stack
- pushf ; push the flags back on
- pop ax ; get the pushed flags
- ; into ax
- popf ; Restore the flags
- test ah,70h ; see if the NT and IOPL flags are still set
- jz YesItIsA286 ; If NT and IOPL not set
- ; it's a 286
- jmp AtLeast386
- YesItIsA286:
- mov ax,2
- jmp detectret
- AtLeast386:
- ; Is It an 80386 or 80486?
- ; Determines whether processor is a 386 or higher. Going into subroutine ax=3
- ; If the processor is a 486, ax will be 4 before leaving. The method is to set
- ; the AC bit of the flags via EAX and the stack. If it stays set, it's a 486.
- mov di,3 ; Store the processor value
- mov bx,sp ; Save sp
- and sp,0fffch ; Prevent alignment fault
- .386
- pushfd ; Preserve the flags
-
- pushfd ; Push so we can get flags
- pop eax ; Get flags into eax
- or eax,40000h ; Set the AC bit
- push eax ; Push back on the stack
- popfd ; Get the value into flags
- pushfd ; Put the value back on stack
- pop eax ; Get value into eax
- popfd ; Restore the flags
- test eax,40000h ; See if the bit is set
- jz YesItIsA386 ; If not we have a 386
- inc di
- YesItIsA386:
- .8086
- mov sp,bx ; Restore sp
- mov ax,di ; Put processor value into ax
- detectret:
- mov EnvVal,ax
- pop es
- pop ds
- pop di
- ret
- ENDP
-
- END
-